#include "util.hpp"
#include <mapbox/geojsonvt/simplify.hpp>
#include <gtest/gtest.h>

using namespace mapbox::geojsonvt;

using P = ProjectedPoint;
using C = ProjectedPoints;

struct Point {
    double a, b;
};

bool operator==(const Point& a, const Point& b) {
    EXPECT_DOUBLE_EQ(a.a, b.a);
    EXPECT_DOUBLE_EQ(a.b, b.b);
    return true;
}

TEST(Simplify, Points) {
    C points{
        P{ 0.22455, 0.25015 }, P{ 0.22691, 0.24419 }, P{ 0.23331, 0.24145 }, P{ 0.23498, 0.23606 },
        P{ 0.24421, 0.23276 }, P{ 0.26259, 0.21531 }, P{ 0.26776, 0.21381 }, P{ 0.27357, 0.20184 },
        P{ 0.27312, 0.19216 }, P{ 0.27762, 0.18903 }, P{ 0.28036, 0.18141 }, P{ 0.28651, 0.17774 },
        P{ 0.29241, 0.15937 }, P{ 0.29691, 0.15564 }, P{ 0.31495, 0.15137 }, P{ 0.31975, 0.14516 },
        P{ 0.33033, 0.13757 }, P{ 0.34148, 0.13996 }, P{ 0.36998, 0.13789 }, P{ 0.38739, 0.14251 },
        P{ 0.39128, 0.13939 }, P{ 0.40952, 0.14114 }, P{ 0.41482, 0.13975 }, P{ 0.42772, 0.12730 },
        P{ 0.43960, 0.11974 }, P{ 0.47493, 0.10787 }, P{ 0.48651, 0.10675 }, P{ 0.48920, 0.10945 },
        P{ 0.49379, 0.10863 }, P{ 0.50474, 0.11966 }, P{ 0.51296, 0.12235 }, P{ 0.51863, 0.12089 },
        P{ 0.52409, 0.12688 }, P{ 0.52957, 0.12786 }, P{ 0.53421, 0.14093 }, P{ 0.53927, 0.14724 },
        P{ 0.56769, 0.14891 }, P{ 0.57525, 0.15726 }, P{ 0.58062, 0.15815 }, P{ 0.60153, 0.15685 },
        P{ 0.61774, 0.15986 }, P{ 0.62200, 0.16704 }, P{ 0.62955, 0.19460 }, P{ 0.63890, 0.19561 },
        P{ 0.64126, 0.20081 }, P{ 0.65177, 0.20456 }, P{ 0.67155, 0.22255 }, P{ 0.68368, 0.21745 },
        P{ 0.69525, 0.21915 }, P{ 0.70064, 0.21798 }, P{ 0.70312, 0.21436 }, P{ 0.71226, 0.21587 },
        P{ 0.72149, 0.21281 }, P{ 0.72781, 0.21336 }, P{ 0.72998, 0.20873 }, P{ 0.73532, 0.20820 },
        P{ 0.73994, 0.20477 }, P{ 0.76998, 0.20842 }, P{ 0.77960, 0.21687 }, P{ 0.78420, 0.21816 },
        P{ 0.80024, 0.21462 }, P{ 0.81053, 0.21973 }, P{ 0.81719, 0.22682 }, P{ 0.82077, 0.23617 },
        P{ 0.82723, 0.23616 }, P{ 0.82989, 0.23989 }, P{ 0.85100, 0.24894 }, P{ 0.85988, 0.25549 },
        P{ 0.86521, 0.26853 }, P{ 0.85795, 0.28030 }, P{ 0.86548, 0.29145 }, P{ 0.86681, 0.29866 },
        P{ 0.86468, 0.30271 }, P{ 0.86779, 0.30617 }, P{ 0.85987, 0.31137 }, P{ 0.86008, 0.31435 },
        P{ 0.85829, 0.31494 }, P{ 0.85810, 0.32760 }, P{ 0.85454, 0.33540 }, P{ 0.86092, 0.34300 },
        P{ 0.85643, 0.35015 }, P{ 0.85142, 0.35296 }, P{ 0.84984, 0.35959 }, P{ 0.85456, 0.36553 },
        P{ 0.84974, 0.37038 }, P{ 0.84409, 0.37189 }, P{ 0.84475, 0.38044 }, P{ 0.84152, 0.38367 },
        P{ 0.83957, 0.39040 }, P{ 0.84559, 0.39905 }, P{ 0.84840, 0.40755 }, P{ 0.84371, 0.41130 },
        P{ 0.84409, 0.41988 }, P{ 0.83951, 0.43276 }, P{ 0.84133, 0.44104 }, P{ 0.84762, 0.44922 },
        P{ 0.84716, 0.45844 }, P{ 0.85138, 0.46279 }, P{ 0.85397, 0.47115 }, P{ 0.86636, 0.48077 }
    };

    const std::vector<Point> simplified = {
        { 0.22455, 0.25015 }, { 0.26776, 0.21381 }, { 0.29691, 0.15564 }, { 0.33033, 0.13757 },
        { 0.40952, 0.14114 }, { 0.4396, 0.11974 },  { 0.48651, 0.10675 }, { 0.52957, 0.12786 },
        { 0.53927, 0.14724 }, { 0.56769, 0.14891 }, { 0.61774, 0.15986 }, { 0.62955, 0.1946 },
        { 0.67155, 0.22255 }, { 0.72781, 0.21336 }, { 0.73994, 0.20477 }, { 0.76998, 0.20842 },
        { 0.7842, 0.21816 },  { 0.80024, 0.21462 }, { 0.82077, 0.23617 }, { 0.85988, 0.25549 },
        { 0.86521, 0.26853 }, { 0.85795, 0.2803 },  { 0.86779, 0.30617 }, { 0.85829, 0.31494 },
        { 0.85454, 0.3354 },  { 0.86092, 0.343 },   { 0.84984, 0.35959 }, { 0.85456, 0.36553 },
        { 0.84409, 0.37189 }, { 0.83957, 0.3904 },  { 0.8484, 0.40755 },  { 0.83951, 0.43276 },
        { 0.85397, 0.47115 }, { 0.86636, 0.48077 }
    };

    Simplify::simplify(points, 0.001);

    std::vector<Point> result;
    for (const auto& p : points) {
        if (p.z > 0.005 * 0.005) {
            result.push_back({ p.x, p.y });
        }
    }

    ASSERT_EQ(simplified, result);
}
